package eu.irreality.dai.ui.keyboard;

import java.awt.AWTKeyStroke;
import java.awt.event.KeyEvent;
import java.util.StringTokenizer;

/**
 * This class is somewhat similar to AWTKeyEvent in the standard API, but it
 * reacts to keycodes on KeyTyped events, and it is generally simplified.
 * 
 * @author Administrador
 * 
 */
public class KeyDescriptor
{

    // private int modifiers;

    private int keyCode;

    private char keyChar;

    private boolean alt;

    private boolean control;

    public KeyDescriptor()
    {
	this.keyCode = KeyEvent.VK_UNDEFINED;
	this.keyChar = KeyEvent.CHAR_UNDEFINED;
    }

    public KeyDescriptor(int keyCode)
    {
	this();
	this.keyCode = keyCode;
    }

    public KeyDescriptor(char keyChar)
    {
	this();
	this.keyChar = keyChar;
    }

    public KeyDescriptor(int keyCode, char keyChar)
    {
	this.keyCode = keyCode;
	this.keyChar = keyChar;
    }

    public KeyDescriptor(int keyCode, char keyChar, boolean alt, boolean control)
    {
	this(keyCode, keyChar);
	this.alt = alt;
	this.control = control;
    }

    /**
     * Creates a key descriptor for a given AWT key event. If the event has an
     * Unicode character associated, the key descriptor will take that char. If
     * not, it will take the event's associated key code.
     * 
     * @param evt
     */
    public KeyDescriptor(KeyEvent evt)
    {
	control = evt.isControlDown();
	alt = evt.isAltDown();
	char ch = evt.getKeyChar();
	if (ch != KeyEvent.CHAR_UNDEFINED && ch != 0)
	{
	    keyChar = ch;
	} else
	{
	    keyCode = evt.getKeyCode();
	}

    }

    /**
     * Creates a key descriptor for a description in the form of a string, such
     * as "v", "V" (distinct), "Ctrl+V", "Ctrl+v"...
     * 
     * @param description
     */
    public KeyDescriptor(String description)
    {
	StringTokenizer st = new StringTokenizer(description, "+");
	while (st.hasMoreTokens())
	{
	    String cur = st.nextToken();
	    if (cur.equalsIgnoreCase("ctrl") || cur.equalsIgnoreCase("control"))
		control = true;
	    else if (cur.equalsIgnoreCase("alt") || cur.equalsIgnoreCase("alt"))
		alt = true;
	    else
	    {
		if (cur.length() == 1)
		{
		    // it's a character
		    keyChar = cur.charAt(0);
		} else
		{
		    // it's a code
		    keyCode = AWTKeyStroke.getAWTKeyStroke(cur).getKeyCode();
		}
	    }
	}
    }

    // public int getModifiers()
    // {
    // return modifiers;
    // }

    public int getKeyCode()
    {
	return keyCode;
    }

    public char getKeyChar()
    {
	return keyChar;
    }

    // public void setModifiers(int modifiers)
    // {
    // this.modifiers = modifiers;
    // }

    public void setKeyCode(int keyCode)
    {
	this.keyCode = keyCode;
    }

    public void setKeyChar(char keyChar)
    {
	this.keyChar = keyChar;
    }

    @Override
    public boolean equals(Object obj)
    {
	if (this == obj)
	{
	    return true;
	}
	if ((obj == null) || (obj.getClass() != this.getClass()))
	{
	    return false;
	}
	KeyDescriptor kd = (KeyDescriptor) obj;
	if (this.alt != kd.alt)
	    return false;
	if (this.control != kd.control)
	    return false;
	if (this.keyChar != KeyEvent.CHAR_UNDEFINED && this.keyChar != 0)
	{
	    return this.keyChar == kd.keyChar;
	}
	// return (this.keyCode == kd.keyCode) && (this.modifiers ==
	// kd.modifiers);
	return (this.keyCode == kd.keyCode);
    }

    @Override
    public int hashCode()
    {
	int hash = 7;
	if (keyChar != KeyEvent.CHAR_UNDEFINED)
	{
	    hash = 31 * hash + keyChar;
	} else
	{
	    hash = 31 * hash + keyCode;
	    // hash = 31 * hash + modifiers;
	}
	if (alt)
	    hash = 31 * hash + 1;
	if (control)
	    hash = 31 * hash + 1;

	return hash;
    }

    public String toString()
    {
	StringBuffer result = new StringBuffer();
	if (control)
	    result.append("Ctrl+");
	if (alt)
	    result.append("Alt+");
	if (keyChar != KeyEvent.CHAR_UNDEFINED && this.keyChar != 0)
	    return result.append(keyChar).toString();
	else
	    return result.append(KeyEvent.getKeyText(keyCode)).toString();
    }

    /**
     * 
     * @return The modifiers in KeyEvent format.
     */
    public int getModifiers()
    {
	int theMods = 0;
	if (control)
	    theMods |= KeyEvent.CTRL_DOWN_MASK;
	if (alt)
	    theMods |= KeyEvent.ALT_DOWN_MASK;
	return theMods;
    }

}
